//! File: Vectors.h
//!
//! Various mathemathical vectors. Not really necessary as Ogre has
//! its own vector classes already.
//!
//! From the RuneEmu project.
//!

#pragma once

#include <Ogre.h>


namespace Shared
{

	template <typename T>	
	class Vector2
	{
	public:
		T x;
		T y;

		Vector2(T _x = 0, T _y = 0) {Set(_x, _y);}
		void Set(T _x, T _y) {x = _x; y = _y;}

		bool operator==(Vector2 const & v) const
		{
			if(x == v.x && y == v.y) return true;
			return false;
		}

		bool operator !=(Vector2 const & v) const
		{
			return ! (v == *this);
		}

		Vector2 operator+(Vector2 /*const &*/ v) const
		{
			Vector2 t(*this);
			t.x += v.x;
			t.y += v.y;
			return t;
		}

		void operator+=(Vector2 /*const &*/ v)
		{
			x += v.x;
			y += v.y;
		}

		void operator-=(Vector2 /*const &*/ v) 
		{
			x -= v.x;
			y -= v.y;
		}

		Vector2 operator-(Vector2 /*const &*/ v) const
		{
			Vector2 t(*this);
			t.x -= v.x;
			t.y -= v.y;
			return t;
		}

		template <typename Type>
		Vector2 operator*(Type /*const &*/ t) const
		{
			Vector2 v(*this);
			v.x *= t;
			v.y *= t;
			return v;
		}

		template <typename Type>
		void operator*=(Type /*const &*/ t)
		{
			x *= t;
			y *= t;
		}

		// Returns cross-product
		T operator*(Vector2 /*const &*/ v) const
		{
			return (this->x * v.x + this->y * v.y);
		}


		inline Vector2 DotProduct(Vector2 v) const
		{
			return *this * v;
		}

	};


	template <typename T>
	class Vector3
	{
	public:
		T x;
		T y;
		T z;
		Vector3(T _x = 0, T _y = 0, T _z = 0) {Set(_x, _y, _z);}
		void Set(T _x, T _y, T _z) {x = _x; y = _y; z = _z;}


		template <typename Type>
		Vector3 operator*(Type const & t)
		{
			Vector3 v(*this);
			v.x *= t;
			v.y *= t;
			v.z *= t;
			return v;
		}

		template <typename Type>
		void operator*=(Type const & t)
		{
			x *= t;
			y *= t;
			z *= t;
		}

		// Returns cross-product
		T operator*(Vector3 const & v)
		{
			return (this->x * v.x + this->y * v.y + this->z * v.z);
		}


		inline Vector3 DotProduct(Vector3 const & v)
		{
			return *this * v;
		}
	};


	template <typename T>
	class Vector4
	{
	public:
		T x;
		T y;
		T z;
		T w;
		Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) {Set(_x, _y, _z, _w);}
		void Set(T _x, T _y, T _z, T _w) {x = _x; y = _y; z = _z; w = _w;}
	};

}



	typedef Ogre::Vector4 Vector4f;
	typedef Ogre::Vector3 Vector3f;
	typedef Ogre::Vector2 Vector2f;